package com.ncepu.clubmanagement.service.impl;

import com.ncepu.clubmanagement.exception.FileUploadException;
import com.ncepu.clubmanagement.mapper.UrlResourceMapper;
import com.ncepu.clubmanagement.pojo.UrlResource;
import com.ncepu.clubmanagement.service.UploadAssist.FileUrlProvider;
import com.ncepu.clubmanagement.service.UploadAssist.FileUrlUpdater;
import com.ncepu.clubmanagement.service.UploadService;
import com.ncepu.clubmanagement.utils.FileNameGenerateUtils;
import com.ncepu.clubmanagement.utils.FileSaveUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.util.List;


@Service
@Slf4j
public class UploadServiceImpl implements UploadService {

    @Autowired
    private FileNameGenerateUtils fileNameGenerateUtils;

    @Autowired
    private FileSaveUtils fileSaveUtils;

    @Autowired
    private UrlResourceMapper urlResourceMapper;


    // 提供尽量安全的，较合理的上传逻辑。唯一的错误就是访问的对象不存在，前端做好处理即可。
    @Override
    @Transactional
    public String universalUploadFile(String fileName, String filePath, MultipartFile file,
                                      FileUrlProvider fileUrlProvider, FileUrlUpdater fileUrlUpdater,
                                      String label) throws Exception{

        // 0. 判断文件是否为空
        if (file == null || file.isEmpty()) {
            throw new FileUploadException("文件为空错误！");
        }

        // 1. 使用用户定义的方法获取原始的URL
        String url_pre = fileUrlProvider.getFileUrl();
        // 创建文件名称(标志)
        String originalName = fileName+label;
        String name = fileNameGenerateUtils.generateFileName(originalName);

        // 2. 没有原来的url
        if (url_pre == null){
            url_pre = fileSaveUtils.generateFileUrl(filePath, name);
            fileUrlUpdater.updateFileUrl(url_pre);
        }

        // 3. 有url或已经生成了url
        // 添加文件
        String url_new = fileSaveUtils.upload(file,filePath,fileName,url_pre);
        if (url_new == null) {
            // 文件上传失败，远端没有处理成功，报错，直接返回
            throw new FileUploadException();
        }
        // 成功，返回最终的url
        return url_new;
    }

    // 如果是在新建一条数据时调用此接口, FileUrlProvider提供为null即可
    public void universalMoveFile(String fileName, String filePath, String sourceUrl,
                                      FileUrlProvider fileUrlProvider, FileUrlUpdater fileUrlUpdater,
                                      String label) throws Exception{
        // 1. 使用用户定义的方法获取原始的URL
        String url_pre = fileUrlProvider.getFileUrl();
        // 创建文件名称(标志)
        String originalName = fileName+label;
        String name = fileNameGenerateUtils.generateFileName(originalName);

        // 2. 没有原来的url
        if (url_pre == null){
            url_pre = fileSaveUtils.generateFileUrl(filePath, name);
            fileUrlUpdater.updateFileUrl(url_pre);
        }

        // 3. 有url或已经生成了url
        // 更换文件
        if(! fileSaveUtils.replaceFile(sourceUrl,url_pre)){
            //更换失败，报错
            throw new FileUploadException();
        }
    }


    @Override
    @Transactional(propagation = Propagation.REQUIRES_NEW)  // 事务独立，避免产生“没有归宿的”文件/URL
    // 上传文件并记录，通常用于事务等逻辑中
    public String uploadFileWithRecord(String fileName,String filePath,MultipartFile file,
                                       String label) throws FileUploadException {
        // 0. 判断文件是否为空
        if (file == null || file.isEmpty()) {
            throw new FileUploadException("文件为空错误！");
        }

        //1. 创建文件名称(标志)
        String originalName = fileName+label;
        String name = fileNameGenerateUtils.generateFileName(originalName);

        // 2. 生成url但不加入
        String url_pre = fileSaveUtils.generateFileUrl(filePath, name);

        // 3. 记录进入相关数据库中
        urlResourceMapper.insertUrlResource(new UrlResource(url_pre,UrlResource.URL_RESOURCE_UNUSED));

        // 4. 上传文件
        String url_new = fileSaveUtils.upload(file,filePath,fileName,url_pre);
        if (url_new == null) {
            log.info("url为空");
            // 文件上传失败，远端没有处理成功，报错，直接返回
            throw new FileUploadException();
        }
        return url_new;
    }


    public void releaseUrlResource(String url) {
        if (url == null) {
            log.info("url为空");
            return;
        }
        urlResourceMapper.updateUrlResourceByUrl(new UrlResource(url,UrlResource.URL_RESOURCE_UNUSED));
    }

    @Override
    public void setUrlResourceUsed(String url) {
        if (url == null) {
            log.info("url为空");
            return;
        }
        urlResourceMapper.updateUrlResourceByUrl(new UrlResource(url,UrlResource.URL_RESOURCE_USED));
    }

    @Override
    public void setUrlResourceUsed(List<String> urls) {
        if (urls == null) {
            log.info("url为空");
            return;
        }
        for (String url : urls) {
            urlResourceMapper.updateUrlResourceByUrl(new UrlResource(url,UrlResource.URL_RESOURCE_USED));
        }
    }


    // 针对文件上传的，不使用url_resource表服务的，需要删除调用此方法（使用url_resource资源的会自动删除）
    @Transactional
    @Override
    public void deleteUrlResourceNotInTable(String url) {
        if (url == null) {
            log.info("url为空");
            return;
        }
        fileSaveUtils.delete(url);
    }



}
